﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Measure
{
  public enum PointerMode
  {
    None,
    Select,
    Pan,
    ZoomIn,
    ZoomOut
  }

  public partial class MainForm : Form
  {
    private HalconDotNet.HWindow hWindow = null;
    private HalconDotNet.HImage hImage = null;
    private int imageWidth = 0;
    private int imageHeight = 0;
    private PointerMode pointerMode = PointerMode.None;
    private double lastImageX = 0.0;
    private double lastImageY = 0.0;

    private static int nextSaveNumber = 0;

    public MainForm()
    {
      InitializeComponent();
    }

    private void MainForm_Load(object sender, EventArgs e)
    {
      hWindow = hImageControl.HalconWindow;

      UIItems.Add(new Action(UpdateSaveImage));
      UIItems.Add(new Action(UpdateSelect));
      UIItems.Add(new Action(UpdatePan));
      UIItems.Add(new Action(UpdateZoomIn));
      UIItems.Add(new Action(UpdateZoomOut));
      UIItems.Add(new Action(UpdateFit));
      UIItems.Add(new Action(Update1To1));
      Application.Idle += new EventHandler(UIItems.UpdateCmdUI);
    }

    private void UpdateSaveImage()
    {
      toolButtonSaveImage.Enabled = (hImage != null);
    }

    private void UpdateSelect()
    {
      if (pointerMode == PointerMode.Select)
      {
        toolButtonSelect.CheckState = CheckState.Checked;
      }
      else
      {
        toolButtonSelect.CheckState = CheckState.Unchecked;
      }
    }

    private void UpdatePan()
    {
      toolButtonPan.Enabled = (hImage != null);
      if (pointerMode == PointerMode.Pan)
      {
        toolButtonPan.CheckState = CheckState.Checked;
      }
      else
      {
        toolButtonPan.CheckState = CheckState.Unchecked;
      }
    }

    private void UpdateZoomIn()
    {
      toolButtonZoomIn.Enabled = (hImage != null);
      if (pointerMode == PointerMode.ZoomIn)
      {
        toolButtonZoomIn.CheckState = CheckState.Checked;
      }
      else
      {
        toolButtonZoomIn.CheckState = CheckState.Unchecked;
      }
    }

    private void UpdateZoomOut()
    {
      toolButtonZoomOut.Enabled = (hImage != null);
      if (pointerMode == PointerMode.ZoomOut)
      {
        toolButtonZoomOut.CheckState = CheckState.Checked;
      }
      else
      {
        toolButtonZoomOut.CheckState = CheckState.Unchecked;
      }
    }

    private void UpdateFit()
    {
      toolButtonFit.Enabled = (hImage != null);
    }

    private void Update1To1()
    {
      toolButton1To1.Enabled = (hImage != null);
    }

    private void hImageControl_HMouseMove(object sender, HalconDotNet.HMouseEventArgs e)
    {
      if (pointerMode == PointerMode.Pan && hImageControl.Capture)
      {
        double dX = ((e.X - lastImageX));
        double dY = ((e.Y - lastImageY));

        if (((int)dX != 0) || ((int)dY != 0))
        {
          PanImage(-dX, -dY);
          lastImageX = e.X - dX;
          lastImageY = e.Y - dY;
          Repaint();
        }
      }

      if (pointerMode == PointerMode.None)
      {
        SetCoordinatesStrip(e);
        SetPixelStrip(e);
      }
    }

    private void SetCoordinatesStrip(HalconDotNet.HMouseEventArgs e)
    {
      toolStripRow.Text = string.Format("行：{0,-7:F2}", e.Y);
      toolStripColumn.Text = string.Format("列：{0,-7:F2}", e.X);
    }

    private void SetPixelStrip(HalconDotNet.HMouseEventArgs e)
    {
      if (hImage == null)
      {
        return;
      }

      if (e.X < 0 || e.Y < 0 || (e.X > imageWidth - 1) || (e.Y > imageHeight - 1))
      {
        toolStripPixel.Text = "像素值：";
        return;
      }

      int numChannels = hImage.CountChannels().I;
      string strPixel = "像素值：";

      if (numChannels > 1)
      {
        strPixel += "(";
      }

      for (int n = 1; n <= numChannels; ++n)
      {
        double grayVal = hImage.AccessChannel(n).GetGrayval((int)Math.Round(e.Y),
          (int)Math.Round(e.X));

        grayVal = Math.Round(grayVal, 2);
        strPixel += grayVal.ToString();

        if (n < numChannels)
        {
          strPixel += ",";
        }
      }

      if (numChannels > 1)
      {
        strPixel += ")";
      }

      toolStripPixel.Text = strPixel;
    }

    private void OpenImage_Click(object sender, EventArgs e)
    {
      OpenFileDialog dlg = new OpenFileDialog();
      dlg.Title = "打开图像文件";
      dlg.Filter = "All Image Files|*.bmp;*.gif;*.jpeg;*.jpg;*.jfif;*.png;*.tif;*.tiff|" +
        "Windows Bitmap (*.bmp)|*.bmp|" +
        "Graphics Interchange Format (*.gif)|*.gif|" +
        "JPEG File Interchange Format (*.jpg)|*.jpg;*.jpeg;*.jfif|" +
        "Portable Network Graphics (*.png)|*.png|" +
        "Tag Image File Format (*.tif)|*.tif;*.tiff|" +
        "All Files (*.*)|*.*";

      if (dlg.ShowDialog() != DialogResult.OK)
      {
        return;
      }

      try
      {
        hImage = new HalconDotNet.HImage(dlg.FileName);

        hImage.GetImageSize(out imageWidth, out imageHeight);
        FitImage();
        Repaint();

        toolStripImageWidth.Text = "图像宽度：" + imageWidth.ToString();
        toolStripImageHeight.Text = "图像高度：" + imageHeight.ToString();
      }
      catch (HalconDotNet.HOperatorException ex)
      {
        MessageBox.Show(this, ex.Message, "打开图像文件错误");
      }
    }

    private void FitImage()
    {
      double aspectRatio = imageWidth / (imageHeight + 0.0);
      double wndAspectRatio = hImageControl.WindowSize.Width /
        (hImageControl.WindowSize.Height + 0.0);

      int dispWidth = imageWidth;
      int dispHeight = imageHeight;
      if (aspectRatio > wndAspectRatio)
      {
        dispWidth = Math.Max(hImageControl.WindowSize.Width, imageWidth);
        dispHeight = (int)Math.Round(dispWidth / wndAspectRatio);
      }
      else
      {
        dispHeight = Math.Max(hImageControl.WindowSize.Height, imageHeight);
        dispWidth = (int)Math.Round(dispHeight * wndAspectRatio);
      }

      int left = (imageWidth - dispWidth) / 2;
      int top = (imageHeight - dispHeight) / 2;

      hImageControl.ImagePart = new Rectangle(left, top, dispWidth, dispHeight);
    }

    private void Zoom1to1Image()
    {
      Rectangle newPart = new Rectangle();
      newPart.X = 0;
      newPart.Y = 0;
      newPart.Width = hImageControl.ClientSize.Width;
      newPart.Height = hImageControl.ClientSize.Height;
      hImageControl.ImagePart = newPart;
    }

    private void PanImage(double dx, double dy)
    {
      Rectangle newPart = hImageControl.ImagePart;
      newPart.Offset((int)Math.Round(dx), (int)Math.Round(dy));
      hImageControl.ImagePart = newPart;
    }

    private void ZoomImage(double x, double y, double scale)
    {
      Rectangle oldPart = hImageControl.ImagePart;

      double percentC = (x - oldPart.X) / oldPart.Width;
      double percentR = (y - oldPart.Y) / oldPart.Height;

      double lengthC = oldPart.Width * scale;
      double lengthR = oldPart.Height * scale;

      int lenC = (int)Math.Round(lengthC);
      int lenR = (int)Math.Round(lengthR);

      Rectangle newPart = new Rectangle();
      newPart.X = (int)Math.Round(x - lengthC * percentC);
      newPart.Y = (int)Math.Round(y - lengthR * percentR);
      newPart.Width = (lenC > 0) ? lenC : 1;
      newPart.Height = (lenR > 0) ? lenR : 1;
      hImageControl.ImagePart = newPart;
    }

    private void hImageControl_Paint(object sender, PaintEventArgs e)
    {
      Repaint();
    }

    private void Repaint()
    {
      HalconDotNet.HSystem.SetSystem("flush_graphic", "false");
      hWindow.ClearWindow();
      HalconDotNet.HSystem.SetSystem("flush_graphic", "true");

      try
      {
        hWindow.DispObj(hImage);
      }
      catch (HalconDotNet.HOperatorException)
      {
      }
    }
    private void SaveImage_Click(object sender, EventArgs e)
    {
      SaveFileDialog dlg = new SaveFileDialog();
      dlg.Title = "保存图像文件";
      dlg.AddExtension = true;
      dlg.FileName = "Image" + (nextSaveNumber++).ToString();
      dlg.Filter = "Portable Network Graphics (*.png)|*.png|" +
        "Windows Bitmap (*.bmp)|*.bmp|" +
        "JPEG File Interchange Format (*.jpg)|*.jpg;*.jpeg;*.jfif|" +
        "Tag Image File Format (*.tif)|*.tiff;*.tif";

      if (dlg.ShowDialog() != DialogResult.OK)
      {
        return;
      }

      string format = null;
      switch (dlg.FilterIndex)
      {
        case 1: format = "png"; break;
        case 2: format = "bmp"; break;
        case 3: format = "jpeg"; break;
        case 4: format = "tiff"; break;
        default: format = "png"; break;
      }

      hImage.WriteImage(format, 0, dlg.FileName);
    }

    private void FToolStripMenuItem_DropDownOpening(object sender, EventArgs e)
    {
      menuItemSaveImage.Enabled = (hImage != null);
    }

    private void hImageControl_HMouseDown(object sender, HalconDotNet.HMouseEventArgs e)
    {
      switch (pointerMode)
      {
        case PointerMode.None:
        case PointerMode.Select:
          break;

        case PointerMode.Pan:
          lastImageX = e.X;
          lastImageY = e.Y;
          hImageControl.Capture = true;
          break;

        case PointerMode.ZoomIn:
          ZoomImage(e.X, e.Y, 0.9);
          Repaint();
          break;

        case PointerMode.ZoomOut:
          ZoomImage(e.X, e.Y, 10/9.0);
          Repaint();
          break;

        default:
          break;
      }
    }

    private void hImageControl_HMouseUp(object sender, HalconDotNet.HMouseEventArgs e)
    {
      if (hImageControl.Capture)
      {
        hImageControl.Capture = false;
      }
    }

    private void toolButtonSelect_Click(object sender, EventArgs e)
    {
      if (pointerMode == PointerMode.Select)
      {
        pointerMode = PointerMode.None;
      }
      else
      {
        pointerMode = PointerMode.Select;
      }

      hImageControl.HalconWindow.SetMshape("arrow");
    }

    private void toolButtonDeleteSelected_Click(object sender, EventArgs e)
    {

    }

    private void toolButtonPan_Click(object sender, EventArgs e)
    {
      if (pointerMode == PointerMode.Pan)
      {
        pointerMode = PointerMode.None;
        hImageControl.HalconWindow.SetMshape("arrow");
      }
      else
      {
        pointerMode = PointerMode.Pan;
        hImageControl.HalconWindow.SetMshape("Size All"); ;
      }
    }

    private void toolButtonZoomIn_Click(object sender, EventArgs e)
    {
      if (pointerMode == PointerMode.ZoomIn)
      {
        pointerMode = PointerMode.None;
      }
      else
      {
        pointerMode = PointerMode.ZoomIn;
      }
      hImageControl.HalconWindow.SetMshape("arrow");
    }

    private void toolButtonZoomOut_Click(object sender, EventArgs e)
    {
      if (pointerMode == PointerMode.ZoomOut)
      {
        pointerMode = PointerMode.None;
      }
      else
      {
        pointerMode = PointerMode.ZoomOut;
      }
      hImageControl.HalconWindow.SetMshape("arrow");
    }

    private void toolButtonFit_Click(object sender, EventArgs e)
    {
      pointerMode = PointerMode.None;
      hImageControl.HalconWindow.SetMshape("arrow");
      FitImage();
      Repaint();
    }

    private void toolButton1To1_Click(object sender, EventArgs e)
    {
      pointerMode = PointerMode.None;
      hImageControl.HalconWindow.SetMshape("arrow");
      Zoom1to1Image();
      Repaint();
    }
  }
}
